package com.freeter.http;

import org.apache.commons.codec.digest.HmacAlgorithms;
import org.apache.commons.codec.digest.HmacUtils;
import org.apache.commons.codec.digest.Md5Crypt;
import org.apache.commons.lang3.StringUtils;
import org.apache.http.HttpEntity;
import org.apache.http.HttpHeaders;
import org.apache.http.NameValuePair;
import org.apache.http.client.methods.*;
import org.apache.http.client.utils.URIBuilder;
import org.apache.http.entity.StringEntity;
import org.apache.http.impl.client.CloseableHttpClient;
import org.apache.http.impl.client.HttpClientBuilder;

import javax.net.ssl.*;
import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.io.UnsupportedEncodingException;
import java.nio.charset.Charset;
import java.security.GeneralSecurityException;
import java.security.InvalidKeyException;
import java.security.NoSuchAlgorithmException;
import java.security.SecureRandom;
import java.security.cert.X509Certificate;
import java.util.Base64;
import java.util.Comparator;
import java.util.List;
import java.util.Objects;
import java.util.concurrent.TimeUnit;

/**
 * 提供一些命令行命令的工具
 *
 * @Author Wang_Chong
 * @Date 2019-12-28 14:58
 * @implementation_function
 * @Version 1.0
 */
public class DataHttpUtil {
    private static final String APPKEY_HEADER = "X-AURORA-APPKEY";
    private static final String SIGN_HEADER = "X-AURORA-SIGN";
    private static final String TIMESTAMP_HEADER = "X-AURORA-TIMESTAMP";
    private static final String CONTENT_MD5 = "CONTENT-MD5";

    /**
     * 飞书同步数据post
     *
     * @param url
     * @param body
     * @param token
     * @return
     * @throws GeneralSecurityException
     * @throws IOException
     */
    public static String fsPost(String url, String body, String token) throws GeneralSecurityException, IOException {
        CloseableHttpResponse response = null;
        CloseableHttpClient httpClient = null;
        try {
            // 获得Http客户端
            httpClient = HttpConnectionPoolUtil.getHttpClient();
            // 创建post请求
            HttpPost httpPost = new HttpPost(url);
            httpPost.setEntity(new StringEntity(body, Charset.forName("UTF-8")));
            httpPost.setHeader(HttpHeaders.CONTENT_TYPE, "application/json; charset=UTF-8");
            if (StringUtils.isNotBlank(token)) {
                httpPost.setHeader(HttpHeaders.AUTHORIZATION, "Bearer " + token);
            }
            // 由客户端执行(发送)post请求
            response = httpClient.execute(httpPost);
            // 从响应模型中获取响应实体
            HttpEntity responseEntity = response.getEntity();
            String result = streamToString(responseEntity);
            httpPost.abort();
            return result;
        } finally {
            // 释放资源
//            if (httpClient != null) {
//                httpClient.close();
//            }
            if (response != null) {
                response.close();
            }
        }
    }

    /**
     * 飞书get请求
     *
     * @param url
     * @param token
     * @return
     * @throws GeneralSecurityException
     * @throws IOException
     */
    public static String fsGet(String url, String token) throws GeneralSecurityException, IOException {
        CloseableHttpClient httpClient = null;
        CloseableHttpResponse response = null;
        try {
            // 获得Http客户端
            httpClient = HttpConnectionPoolUtil.getHttpClient();
            // 创建post请求
            HttpGet httpGet = new HttpGet(url);
            httpGet.setHeader(HttpHeaders.CONTENT_TYPE, "application/json; charset=UTF-8");
            if (StringUtils.isNotBlank(token)) {
                httpGet.setHeader(HttpHeaders.AUTHORIZATION, "Bearer " + token);
            }
            // 由客户端执行(发送)get请求
            response = httpClient.execute(httpGet);
            // 从响应模型中获取响应实体
            HttpEntity responseEntity = response.getEntity();
            String res = streamToString(responseEntity);
            httpGet.abort();
            return res;
        } finally {
            // 释放资源
//            if (httpClient != null) {
//                httpClient.close();
//            }
            if (response != null) {
                response.close();
            }
        }
    }

    //请求飞书的api
    public static String post(String url, String body, String token) throws GeneralSecurityException, IOException {
        // 获得Http客户端
        CloseableHttpClient httpClient = HttpClientBuilder.create()
                .setSSLContext(getAllTrustedSslContext())
                .setConnectionTimeToLive(5, TimeUnit.SECONDS)
                .setSSLHostnameVerifier(getAllTrustedVerifier()).build();

        // 创建post请求
        HttpPost httpPost = new HttpPost(url);
        httpPost.setEntity(new StringEntity(body, Charset.forName("UTF-8")));
        httpPost.setHeader(HttpHeaders.CONTENT_TYPE, "application/json; charset=UTF-8");
        if (StringUtils.isNotBlank(token)) {
            httpPost.setHeader(HttpHeaders.AUTHORIZATION, "Bearer " + token);
        }

        // 由客户端执行(发送)post请求
        CloseableHttpResponse response = httpClient.execute(httpPost);
        // 从响应模型中获取响应实体
        HttpEntity responseEntity = response.getEntity();

        String result = streamToString(responseEntity);
        // 释放资源
        if (httpClient != null) {
            httpClient.close();
        }
        if (response != null) {
            response.close();
        }
        return result;
    }

    public static String post(String url, String body, String token, String appKey, int expireTimes, String signatureNonce) throws GeneralSecurityException, IOException {
        // 获得Http客户端
        CloseableHttpClient httpClient = HttpClientBuilder.create()
                .setSSLContext(getAllTrustedSslContext())
                .setConnectionTimeToLive(5, TimeUnit.SECONDS)
                .setSSLHostnameVerifier(getAllTrustedVerifier()).build();

        // 创建post请求
        HttpPost httpPost = new HttpPost(url);
        httpPost.setEntity(new StringEntity(body, Charset.forName("UTF-8")));
        httpPost.setHeader(HttpHeaders.CONTENT_TYPE, "application/json; charset=UTF-8");
        if (StringUtils.isNotBlank(token)) {
            httpPost.setHeader(HttpHeaders.AUTHORIZATION, "Bearer " + token);
        }

        // 由客户端执行(发送)post请求
        CloseableHttpResponse response = httpClient.execute(httpPost);
        // 从响应模型中获取响应实体
        HttpEntity responseEntity = response.getEntity();

        String result = streamToString(responseEntity);
        // 释放资源
        if (httpClient != null) {
            httpClient.close();
        }
        if (response != null) {
            response.close();
        }
        return result;
    }


    public static String post(String url, String body, String appKey, String appSecret)
            throws GeneralSecurityException, IOException {
        // 获得Http客户端
        CloseableHttpClient httpClient = HttpClientBuilder.create()
                .setSSLContext(getAllTrustedSslContext())
                .setConnectionTimeToLive(5, TimeUnit.SECONDS)
                .setSSLHostnameVerifier(getAllTrustedVerifier()).build();

        // 创建post请求
        HttpPost httpPost = new HttpPost(url);
        httpPost.setEntity(new StringEntity(body, Charset.forName("UTF-8")));
        httpPost.setHeader(HttpHeaders.CONTENT_TYPE, "application/json; charset=UTF-8");
        doSign(httpPost, body.getBytes(), appKey, appSecret);

        // 由客户端执行(发送)post请求
        CloseableHttpResponse response = httpClient.execute(httpPost);
        // 从响应模型中获取响应实体
        HttpEntity responseEntity = response.getEntity();

        String result = streamToString(responseEntity);
        // 释放资源
        if (httpClient != null) {
            httpClient.close();
        }
        if (response != null) {
            response.close();
        }
        return result;
    }


    public static String get(String url, String token)
            throws GeneralSecurityException, IOException {
        // 获得Http客户端
        CloseableHttpClient httpClient = HttpClientBuilder.create()
                .setSSLContext(getAllTrustedSslContext())
                .setConnectionTimeToLive(5, TimeUnit.SECONDS)
                .setSSLHostnameVerifier(getAllTrustedVerifier()).build();

        // 创建post请求
        HttpGet httpGet = new HttpGet(url);
        httpGet.setHeader(HttpHeaders.CONTENT_TYPE, "application/json; charset=UTF-8");
        if (StringUtils.isNotBlank(token)) {
            httpGet.setHeader(HttpHeaders.AUTHORIZATION, "Bearer " + token);
        }

        // 由客户端执行(发送)get请求
        CloseableHttpResponse response = httpClient.execute(httpGet);
        // 从响应模型中获取响应实体
        HttpEntity responseEntity = response.getEntity();
        String res = streamToString(responseEntity);
        // 释放资源
        if (httpClient != null) {
            httpClient.close();
        }
        if (response != null) {
            response.close();
        }
        return res;
    }

    private static void get(String url, String appKey, String appSecret)
            throws GeneralSecurityException, IOException {
        // 获得Http客户端
        CloseableHttpClient httpClient = HttpClientBuilder.create()
                .setSSLContext(getAllTrustedSslContext())
                .setConnectionTimeToLive(5, TimeUnit.SECONDS)
                .setSSLHostnameVerifier(getAllTrustedVerifier()).build();

        // 创建post请求
        HttpGet httpGet = new HttpGet(url);
        httpGet.setHeader(HttpHeaders.CONTENT_TYPE, "application/json; charset=UTF-8");
        doSign(httpGet, null, appKey, appSecret);

        // 由客户端执行(发送)get请求
        CloseableHttpResponse response = httpClient.execute(httpGet);
        // 从响应模型中获取响应实体
        HttpEntity responseEntity = response.getEntity();
        System.out.println(streamToString(responseEntity));
        // 释放资源
        if (httpClient != null) {
            httpClient.close();
        }
        if (response != null) {
            response.close();
        }
    }

    private static SSLContext getAllTrustedSslContext() throws GeneralSecurityException {
        TrustManager[] trustAllCerts = new TrustManager[]{new X509TrustManager() {
            @Override
            public X509Certificate[] getAcceptedIssuers() {
                return new X509Certificate[0];
            }

            @Override
            public void checkClientTrusted(X509Certificate[] chain, String authType) {
            }

            @Override
            public void checkServerTrusted(X509Certificate[] chain, String authType) {
            }
        }};

        SSLContext context = SSLContext.getInstance("TLS");
        context.init((KeyManager[]) null, trustAllCerts, new SecureRandom());
        return context;
    }

    private static HostnameVerifier getAllTrustedVerifier() {
        return new HostnameVerifier() {
            @Override
            public boolean verify(String hostname, SSLSession session) {
                return true;
            }
        };
    }

    private static void doSign(HttpRequestBase httpRequestBase, byte[] body, String appKey, String appSecret)
            throws NoSuchAlgorithmException, UnsupportedEncodingException, InvalidKeyException {
        String method = httpRequestBase.getMethod().toUpperCase();
        URIBuilder uriBuilder = new URIBuilder(httpRequestBase.getURI());
        String queryString = queryJoin(uriBuilder.getQueryParams());
        long timestamp = System.currentTimeMillis();
        // 构造待签字符串
        String stringToSign = null;
        String contentMd5 = null;
        if (httpRequestBase instanceof HttpPost || httpRequestBase instanceof HttpPut) {
            contentMd5 = null == body || body.length == 0 ? "" : Base64.getEncoder().encodeToString(Md5Crypt.md5Crypt(body).getBytes());
            httpRequestBase.setHeader(CONTENT_MD5, contentMd5);

            stringToSign = method + "\n" + queryString + "\n" + timestamp + "\n" + contentMd5;

        } else {
            stringToSign = method + "\n" + queryString + "\n" + timestamp;
        }

        //String signature = new String(new HmacUtils(HmacAlgorithms.HMAC_SHA_256, appSecret).hmacHex(stringToSign).getBytes());
        String signature = "";
        httpRequestBase.setHeader(APPKEY_HEADER, appKey);
        httpRequestBase.setHeader(SIGN_HEADER, signature);
        httpRequestBase.setHeader(TIMESTAMP_HEADER, String.valueOf(timestamp));

        //在postman对应的参数填写
//        System.out.println("&&&&&&&&&&&&&&&&&&&&&&&对应的四个参数和值&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&");
//        System.out.println("APPKEY_HEADER    = 参数一 ： X-AURORA-APPKEY(必传)         = " + appKey);
//        System.out.println("SIGN_HEADER      = 参数二 ： X-AURORA-SIGN(必传)           = " + signature);
//        System.out.println("TIMESTAMP_HEADER = 参数三 ： X-AURORA-TIMESTAMP(必填)      = " + String.valueOf(timestamp));
//        System.out.println("CONTENT_MD5      = 参数四 ： CONTENT_MD5(选填）            = " + contentMd5);
//        System.out.println("&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&");

    }

    private static String queryJoin(List<NameValuePair> query) {
        if (null == query || query.isEmpty()) {
            return "";
        }

        String split = "";
        StringBuilder stringBuilder = new StringBuilder();
        query.sort(new Comparator<NameValuePair>() {
            @Override
            public int compare(NameValuePair o1, NameValuePair o2) {
                return o1.getName().compareTo(o2.getName());
            }
        });
        for (NameValuePair entry : query) {
            stringBuilder.append(split).append(entry.getName());
            if (!Objects.isNull(entry.getValue())) {
                stringBuilder.append("=").append(entry.getValue());
                split = "&";
            }
        }
        return stringBuilder.toString();
    }

    private static String streamToString(HttpEntity httpEntity) throws IOException {
        ByteArrayOutputStream outputStream = new ByteArrayOutputStream();
        httpEntity.writeTo(outputStream);
        return outputStream.toString();
    }
}

